﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using System.Web.Mvc;
using System.Web.Security;
using EmitMapper;
using InnovaApp.Layers.CommonLayer;
using InnovaApp.Layers.DataLayer;
using InnovaApp.Layers.DomainLayer;
using InnovaApp.Layers.ResourcesLayer.Properties;
using InnovaApp.Portals.MVC4Portal.Models;
using InnovaApp.Portals.MVC4Portal.Models.MetaModels.ContactManagement;
using INNOVACALL.Framework.Common;
using INNOVACALL.Framework.Common.CodeFormatting;
using INNOVACALL.Framework.Common.Models;
using INNOVACALL.Framework.Common.MVCHelpers;

namespace InnovaApp.Portals.MVC4Portal.Controllers
{
    public class AdvancedSamples_AddressesManagementController : _Controllers_Base<AdvancedSamples_AddressesManagementModel>
    {
        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {
            base.eMethodBase = "InnovaApp.Portals.InnovaAppFrontOfficePortal.Controllers.AdvancedSamples_AddressesManagementController";
            base.specificCssCollection = new string[] { "_FormCommon.css", "Views/AdvancedSamples_AddressesManagement.css", "ClientComponents/CodeFormatting/csharp.css", "ClientComponents/KendoUI/kendo.common.min.css", "ClientComponents/KendoUI/kendo.blueopal.min.css", "themes/base/jquery-ui.css", "themes/base/jquery.ui.all.css" };
            base.specificJSCollection = null;
            base.dynamicJSCollection = new string[] { "/ScriptsG/inoAdvancedSamples_AddressesManagementDynamic.js" };
            base.specificJqueryJSCollection = new string[] { "", "ClientComponents/KendoUI/kendo.web.min.js", "InnovacallJS/AdvancedSamples_AddressesManagement/AdvancedSamples_AddressesManagement.js" };
            base.externalCSS = null;
            base.Meta.Add(enMeta.Description, Resources.View_AdvancedSamples_AddressesManagement_Meta_Description);
            base.Meta.Add(enMeta.Keywords, Resources.View_AdvancedSamples_AddressesManagement_OrderWithDetails_Meta_Keywords);
            base.Meta.Add(enMeta.Subject, Resources.View_AdvancedSamples_AddressesManagement_OrderWithDetails_Meta_Subject);

            base.Initialize(requestContext);
        }

        [HttpGet, Authorize, CacheManager(enCacheMode.NoCache)]
        public ActionResult Index()
        {
            //NEVER USES VIEW BAG AGAIN !
            //ViewBag.Message = "Modify this template to kick-start your ASP.NET MVC application.";
            using (DataRepositories _dataContext = new DataRepositories())
            {
                base.InitView(
                    Resources.View_AdvancedSamples_AddressesManagement_PageTitle,
                    string.Empty,
                    specificCssCollection,
                    specificJSCollection,
                    dynamicJSCollection,
                    specificJqueryJSCollection,
                    jsVariables,
                    externalCSS,
                    Meta,
                    _dataContext,
                    true);

                Guid currentUserId = (Guid)Membership.GetUser().ProviderUserKey;
                try
                {
                    ContentData.CurrentContact = base.CurrentContactGet(_dataContext);
                    ContentData.Addresses = CurrentUserAddressesGet(currentUserId, _dataContext);
                    PrepareEmptyAddress(_dataContext);
                }
                catch (INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException iDIe)
                {
                    string returnURL = Server.UrlEncode(Request.Url.AbsoluteUri);
                    string ScriptToExecute = string.Format("$.fn.jqDialogAlert('{0}','{1}','{2}{3}');",
                        Resources.View_AdvancedSamples_ErrMsgContactAccountNotCreated_Title,
                        Resources.View_AdvancedSamples_ErrMsgContactAccountNotCreated_Message,
                        "/Sample_BasicForm_MyProfile?ReturnUrl=",
                        returnURL);
                    base.jsVariables = new string[] { "var scriptToExecute='" + ScriptToExecute.Replace("\'", "\\\'") + "'" };
                    ContentData.CurrentAddress = new ContactAddress_MetaModel();
                    ContentData._JSVariables = base.jsVariables.ToList();
                }
            }

            ContentData.InvolvedCode = new InvolvedCodeModel();
            ContentData.InvolvedCode.Add(new INNOVACALL.Framework.Common.Models.MetaModels.CodeFile_MetaModel() { Language = enCodeLanguage.Html, TabStripName = "View", TabStripContent = "/Views/AdvancedSamples_AddressesManagement/Index.cshtml" });
            ContentData.InvolvedCode.Add(new INNOVACALL.Framework.Common.Models.MetaModels.CodeFile_MetaModel() { Language = enCodeLanguage.Html, TabStripName = "Layout", TabStripContent = "/Views/Shared/_Layout.cshtml" });
            ContentData.InvolvedCode.Add(new INNOVACALL.Framework.Common.Models.MetaModels.CodeFile_MetaModel() { Language = enCodeLanguage.cSharp, TabStripName = "Controller", TabStripContent = "/Controllers/AdvancedSamples_AddressesManagementController.cs" });
            ContentData.InvolvedCode.Add(new INNOVACALL.Framework.Common.Models.MetaModels.CodeFile_MetaModel() { Language = enCodeLanguage.cSharp, TabStripName = "Model", TabStripContent = "/Models/AdvancedSamples_AddressesManagementModel.cs" });
            ContentData.InvolvedCode.Add(new INNOVACALL.Framework.Common.Models.MetaModels.CodeFile_MetaModel() { Language = enCodeLanguage.Javascript, TabStripName = "View JS", TabStripContent = "/Scripts/InnovacallJS/AdvancedSamples_AddressesManagement/AdvancedSamples_AddressesManagement.js" });
            ContentData.InvolvedCode.Add(new INNOVACALL.Framework.Common.Models.MetaModels.CodeFile_MetaModel() { Language = enCodeLanguage.Javascript, TabStripName = "Layout JS", TabStripContent = "/Scripts/InnovacallJS/_Layout/_Layout.js" });
            ContentData.InvolvedCode.Add(new INNOVACALL.Framework.Common.Models.MetaModels.CodeFile_MetaModel() { Language = enCodeLanguage.Html, TabStripName = "Script G View", TabStripContent = "/Views/ScriptsG/inoAdvancedSamples_AddressesManagementDynamic.cshtml" });
            ContentData.InvolvedCode.Add(new INNOVACALL.Framework.Common.Models.MetaModels.CodeFile_MetaModel() { Language = enCodeLanguage.GeneratedJavascript, TabStripName = "View Generated JS", TabStripContent = "/ScriptsG/inoAdvancedSamples_AddressesManagementDynamic.js" });
            RenderCodeFiles(ContentData.InvolvedCode);

            return View(ContentData);
        }

        private void PrepareEmptyAddress(DataRepositories _dataContext)
        {
            ContentData.CurrentAddress = new Models.MetaModels.ContactManagement.ContactAddress_MetaModel();
            ContentData.CurrentAddress.Id = -1;
        }

        /// <summary>
        /// Get addresses of current user
        /// </summary>
        /// <param name="currentUserId"></param>
        /// <param name="_dataContext"></param>
        /// <returns></returns>
        private List<SelectListItem> CurrentUserAddressesGet(Guid currentUserId, DataRepositories _dataContext)
        {
            List<SelectListItem> toReturn = new List<SelectListItem>();
            List<ContactAddress> dbContactAddresses = _dataContext.Contact__AdressType__ContactAddress_Rep.Query
                (
                    x =>
                    x.Contact.FK_InnoAppUser == currentUserId
                ).Select(x => x.ContactAddress).Distinct().ToList();
            toReturn = dbContactAddresses.Select(x => new SelectListItem() { Value = x.Id.ToString(), Text = x.Address_1 + " ... [" + x.Town + "]", Selected = false }).ToList();

            return toReturn;
        }

        [HttpPost, Authorize, CacheManager(enCacheMode.NoCache)]
        public JsonResult ContactAddressGet(int id)
        {
            string eMethod = eMethodBase + "ContactAddressGet[POST]";
            object eParameters = new { model = "model" };
            JsonResult toReturn = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            try
            {
                using (DataRepositories _dataContext = new DataRepositories())
                {
                    ContactAddress dbContactAddress;
                    MembershipUser currentUser = Membership.GetUser();
                    dbContactAddress = _dataContext.Contact__AdressType__ContactAddress_Rep.Query(x => x.Contact.FK_InnoAppUser == (Guid)currentUser.ProviderUserKey).Where(x => x.ContactAddress.Id == id).Select(x => x.ContactAddress).FirstOrDefault();
                    ContactAddress_MetaModel ContactAddress = ObjectMapperManager.DefaultInstance.GetMapper<ContactAddress, ContactAddress_MetaModel>().Map(dbContactAddress);
                    AdvancedSamples_AddressesManagementModel model = new AdvancedSamples_AddressesManagementModel();
                    model.CurrentAddress = ContactAddress;
                    model.CurrentAddress.IsPostAddress = dbContactAddress.Contact__AdressType__ContactAddress.Where(x => x.AddressType.isDelivery == false && x.AddressType.isBilling == false).Count() > 0;
                    model.CurrentAddress.IsDeliveryAddress = dbContactAddress.Contact__AdressType__ContactAddress.Where(x => x.AddressType.isDelivery == true).Count() > 0;
                    model.CurrentAddress.IsInvoicingAddress = dbContactAddress.Contact__AdressType__ContactAddress.Where(x => x.AddressType.isBilling == true).Count() > 0;
                    string htmlContent = RenderPartialViewToString("_AdvancedSamples_AddressesManagementRefreshAddress", model);
                    toReturn.Data = new { success = true, htmlContent = htmlContent };
                }
            }
            catch (Exception ex)
            {
                toReturn.Data = new { success = false, message = ex.Message };
            }
            return toReturn;
        }
        [HttpPost, Authorize, CacheManager(enCacheMode.NoCache)]
        //public JsonResult AddUpdate(int id, AdvancedSamples_AddressesManagementModel model)
        public JsonResult AddUpdate(int id)
        {
            Contact__AdressType__ContactAddress dbContact__AdressType__ContactAddress;
            //MVC4 BugFix Model cannot be binded automatically => Old school binding...
            AdvancedSamples_AddressesManagementModel model = new AdvancedSamples_AddressesManagementModel();
            model.CurrentAddress.Id = int.Parse(Request.Form["CurrentAddress.Id"]);
            model.CurrentAddress.IsPostAddress = !(Request.Form["CurrentAddress.IsPostAddress"] == "false");
            model.CurrentAddress.IsInvoicingAddress = !(Request.Form["CurrentAddress.IsInvoicingAddress"] == "false");
            model.CurrentAddress.IsDeliveryAddress = !(Request.Form["CurrentAddress.IsDeliveryAddress"] == "false");
            model.CurrentAddress.Address_1 = Request.Form["CurrentAddress.Address_1"];
            model.CurrentAddress.Address_2 = Request.Form["CurrentAddress.Address_2"];
            model.CurrentAddress.Address_3 = Request.Form["CurrentAddress.Address_3"];
            model.CurrentAddress.ZipCode = Request.Form["CurrentAddress.ZipCode"];
            model.CurrentAddress.Town = Request.Form["CurrentAddress.Town"];
            model.CurrentAddress.Cedex = Request.Form["CurrentAddress.Cedex"];
            model.CurrentAddress.Country = Request.Form["CurrentAddress.Country"];
            string eMethod = eMethodBase + "ContactAddressGet[POST]";
            object eParameters = new { model = "model" };
            JsonResult toReturn = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            ContactAddress dbContactAddress = null;
            Guid currentUserId = (Guid)Membership.GetUser().ProviderUserKey;
            using (DataRepositories _dataContext = new DataRepositories())
            {
                using (TransactionScope TS = new TransactionScope())//Open a transaction to encapsulate multiple actions
                {
                    dbContactAddress = ObjectMapperManager.DefaultInstance.GetMapper<ContactAddress_MetaModel, ContactAddress>().Map(model.CurrentAddress);
                    _dataContext.ContactAddress_Rep.AddUpdate(dbContactAddress);
                    _dataContext.Save();
                    Contact dbContact = _dataContext.Contact_Rep.Query(c => c.FK_InnoAppUser == currentUserId).FirstOrDefault();
                    if (dbContact == null)
                    {
                        throw new INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException(eMethod, eParameters, Resources.View_AdvancedSamples_AddressesManagement_ErrMsgContactNotFound);
                    }
                    //Done here because EntityFramework don't recognize EnumTools.EnumTypeTo
                    int AddressTypePostId = EnumTools.EnumTypeTo<int>(enAddressTypes.Post);
                    int AddressTypeDeliveryId = EnumTools.EnumTypeTo<int>(enAddressTypes.Delivery);
                    int AddressTypeInvoicingId = EnumTools.EnumTypeTo<int>(enAddressTypes.Invoicing);
                    dbContact__AdressType__ContactAddress = _dataContext.Contact__AdressType__ContactAddress_Rep.Query(x => x.ContactAddress.Id == dbContactAddress.Id && x.FK_AddressType == AddressTypePostId).FirstOrDefault();
                    if (model.CurrentAddress.IsPostAddress)
                    {
                        if (dbContact__AdressType__ContactAddress == null)
                        {
                            dbContact__AdressType__ContactAddress = new Contact__AdressType__ContactAddress();
                        }
                        dbContact__AdressType__ContactAddress.FK_ContactAddress = dbContactAddress.Id;
                        dbContact__AdressType__ContactAddress.FK_Contact = dbContact.Id;
                        dbContact__AdressType__ContactAddress.FK_AddressType = AddressTypePostId;
                        _dataContext.Contact__AdressType__ContactAddress_Rep.AddUpdate(dbContact__AdressType__ContactAddress);
                        _dataContext.Save();
                    }
                    else
                    {
                        if (dbContact__AdressType__ContactAddress != null)
                        {
                            _dataContext.Contact__AdressType__ContactAddress_Rep.Remove(dbContact__AdressType__ContactAddress);
                            _dataContext.Save();
                        }
                    }
                    dbContact__AdressType__ContactAddress = _dataContext.Contact__AdressType__ContactAddress_Rep.Query(x => x.ContactAddress.Id == dbContactAddress.Id && x.FK_AddressType == AddressTypeInvoicingId).FirstOrDefault();
                    if (model.CurrentAddress.IsInvoicingAddress)
                    {
                        if (dbContact__AdressType__ContactAddress == null)
                        {
                            dbContact__AdressType__ContactAddress = new Contact__AdressType__ContactAddress();
                        }
                        dbContact__AdressType__ContactAddress = new Contact__AdressType__ContactAddress();
                        dbContact__AdressType__ContactAddress.FK_ContactAddress = dbContactAddress.Id;
                        dbContact__AdressType__ContactAddress.FK_Contact = dbContact.Id;
                        dbContact__AdressType__ContactAddress.FK_AddressType = EnumTools.EnumTypeTo<int>(enAddressTypes.Invoicing);
                        _dataContext.Contact__AdressType__ContactAddress_Rep.AddUpdate(dbContact__AdressType__ContactAddress);
                        _dataContext.Save();
                    }
                    else
                    {
                        if (dbContact__AdressType__ContactAddress != null)
                        {
                            _dataContext.Contact__AdressType__ContactAddress_Rep.Remove(dbContact__AdressType__ContactAddress);
                            _dataContext.Save();
                        }
                    }
                    dbContact__AdressType__ContactAddress = _dataContext.Contact__AdressType__ContactAddress_Rep.Query(x => x.ContactAddress.Id == dbContactAddress.Id && x.FK_AddressType == AddressTypeDeliveryId).FirstOrDefault();
                    if (model.CurrentAddress.IsDeliveryAddress)
                    {
                        dbContact__AdressType__ContactAddress = new Contact__AdressType__ContactAddress();
                        dbContact__AdressType__ContactAddress.FK_ContactAddress = dbContactAddress.Id;
                        dbContact__AdressType__ContactAddress.FK_Contact = dbContact.Id;
                        dbContact__AdressType__ContactAddress.FK_AddressType = EnumTools.EnumTypeTo<int>(enAddressTypes.Delivery);
                        _dataContext.Contact__AdressType__ContactAddress_Rep.AddUpdate(dbContact__AdressType__ContactAddress);
                        _dataContext.Save();
                    }
                    else
                    {
                        if (dbContact__AdressType__ContactAddress != null)
                        {
                            _dataContext.Contact__AdressType__ContactAddress_Rep.Remove(dbContact__AdressType__ContactAddress);
                            _dataContext.Save();
                        }
                    }
                    TS.Complete();
                }

                string htmlContent = RefreshFormHtmlContent(_dataContext, currentUserId, dbContactAddress);
                toReturn.Data = new { @success = true, @htmlContent = htmlContent, @divToUpdate = "#divForm", @scriptToExecute = "$.fn.PrepareForm(" + dbContactAddress.Id + ");" };
            }
            return toReturn;
        }
        [HttpPost, Authorize, CacheManager(enCacheMode.NoCache)]
        public JsonResult Delete(int id)
        {
            string eMethod = eMethodBase + "ContactAddressGet[POST]";
            object eParameters = new { model = "model" };
            JsonResult toReturn = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            Guid currentUserId = (Guid)Membership.GetUser().ProviderUserKey;
            using (DataRepositories _dataContext = new DataRepositories())
            {
                IEnumerable<int> idsJoinsToRemove = _dataContext.Contact__AdressType__ContactAddress_Rep.Query(x => x.Contact.InnoAppUser.Id == currentUserId && x.FK_ContactAddress == id).Select(x => x.Id).AsEnumerable();
                using (TransactionScope TS = new TransactionScope())//Open a transaction to encapsulate multiple actions
                {
                    foreach (int i in idsJoinsToRemove)
                    {
                        _dataContext.Contact__AdressType__ContactAddress_Rep.Remove(_dataContext.Contact__AdressType__ContactAddress_Rep.Query(x => x.Id == i).Single());
                    }
                    _dataContext.Save();
                    _dataContext.ContactAddress_Rep.Remove(_dataContext.ContactAddress_Rep.GetById(id));
                    _dataContext.Save();
                    TS.Complete();
                }
                ContactAddress dbContactAddress = new ContactAddress();
                AdvancedSamples_AddressesManagementModel model = new AdvancedSamples_AddressesManagementModel();
                model.CurrentAddress = new ContactAddress_MetaModel() { Id = -1 };
                string htmlContent = RefreshFormHtmlContent(_dataContext, currentUserId, dbContactAddress);
                toReturn.Data = new { @success = true, @htmlContent = htmlContent, @divToUpdate = "#divForm", @scriptToExecute = "$.fn.PrepareForm(" + dbContactAddress.Id + ");" };
            }
            return toReturn;
        }
        /// <summary>
        /// Render Address list and current address form to string
        /// </summary>
        /// <param name="_dataContext">-1 to select NewAddressItem</param>
        /// <param name="currentAddressId"></param>
        /// <returns></returns>
        private string RefreshFormHtmlContent(DataRepositories _dataContext, Guid currentUserId, ContactAddress dbContactAddress)
        {
            string toReturn = string.Empty;
            AdvancedSamples_AddressesManagementModel model = new AdvancedSamples_AddressesManagementModel();
            model.Addresses = CurrentUserAddressesGet(currentUserId, _dataContext);
            model.CurrentAddress = ObjectMapperManager.DefaultInstance.GetMapper<ContactAddress, ContactAddress_MetaModel>().Map(dbContactAddress);
            if (dbContactAddress.Id >= 1)
            {
                model.CurrentAddress.IsPostAddress = _dataContext.Contact__AdressType__ContactAddress_Rep.Query(x => x.FK_ContactAddress == dbContactAddress.Id && ((x.AddressType.isBilling == true && x.AddressType.isDelivery == true) == false)).Count() > 0;
                model.CurrentAddress.IsDeliveryAddress = _dataContext.Contact__AdressType__ContactAddress_Rep.Query(x => x.FK_ContactAddress == dbContactAddress.Id && x.AddressType.isDelivery == true).Count() > 0;
                model.CurrentAddress.IsInvoicingAddress = _dataContext.Contact__AdressType__ContactAddress_Rep.Query(x => x.FK_ContactAddress == dbContactAddress.Id && x.AddressType.isBilling == true).Count() > 0;
            }
            else
            {
                model.CurrentAddress.IsPostAddress = false;
                model.CurrentAddress.IsDeliveryAddress = false;
                model.CurrentAddress.IsInvoicingAddress = false;
            }
            model.CurrentContact = CurrentContactGet(_dataContext);
            toReturn = base.RenderPartialViewToString("_AdvancedSamples_AddressesManagementRefreshListAndAddress", model);
            return toReturn;
        }
    }
}
